﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using UEExplorer.UI.Tabs;
using UELib;
using UELib.Core;
using UELib.Flags;

namespace Eliot.Extensions.ExecGenerator
{
    [ComVisible(false)]
    public partial class UC_ExecGenerator : UserControl_Tab
    {
        private readonly List<UnrealPackage> _Packages = new List<UnrealPackage>();

        public UC_ExecGenerator()
        {
            InitializeComponent();
        }

        private void Button_Add_Click(object sender, EventArgs e)
        {
            using (var ofd = new OpenFileDialog())
            {
                ofd.DefaultExt = "u";
                ofd.Filter = "UnrealScript(*.u)|*.u";
                ofd.FilterIndex = 1;
                ofd.Title = "File Dialog";
                ofd.Multiselect = true;
                var dr = ofd.ShowDialog(this);
                if (dr != DialogResult.OK)
                {
                    return;
                }

                // Load every selected file from the file dialog
                foreach (string fileName in ofd.FileNames)
                {
                    _Packages.Add(UnrealLoader.LoadPackage(fileName));
                    TreeView_Packages.Nodes.Add(fileName);
                }
            }
        }

        private void Button_Save_Click(object sender, EventArgs e)
        {
            string gameprefix = TextBox_GamePrefix.Text;
            string engineprefix = TextBox_EnginePrefix.Text;

            string buffer = "{{autogenerated}}\r\nEvery [[console command]] declared in [[UnrealScript]] of [[" +
                            gameprefix + "]] is listed here.\r\n";

            _Packages.Sort((p1, p2) => string.CompareOrdinal(p1.PackageName, p2.PackageName));
            foreach (var package in _Packages)
            {
                package.InitializePackage();

                var klasbuffer = string.Empty;
                foreach (var klas in package.Objects.OfType<UClass>())
                {
                    if (klas.Functions == null || !klas.Functions.Any())
                    {
                        continue;
                    }

                    var execfunc = new List<UFunction>();
                    foreach (var func in klas.Functions)
                    {
                        if (func.HasFunctionFlag(FunctionFlags.Exec))
                        {
                            execfunc.Add(func);
                        }
                    }

                    if (execfunc.Count <= 0)
                    {
                        continue;
                    }

                    execfunc.Sort((p1, p2) => string.CompareOrdinal(p1.Name, p2.Name));

                    klasbuffer += "===" + klas.Name + " Commands===\r\n{{main|" + engineprefix + ":" + klas.Name +
                                  " (" + gameprefix + ")}}\r\n";
                    foreach (var func in execfunc)
                    {
                        klasbuffer += "\r\n;" + func.Name + " - '''???.'''";
                        if (func.Params != null && func.Params.Any())
                        {
                            foreach (var prop in func.Params)
                            {
                                string typetext = (prop.Type.ToString() == "Str"
                                    ? "string"
                                    : prop.Type.ToString()).ToLower(CultureInfo.CurrentCulture);

                                string friendlytypetext = prop.GetFriendlyType();
                                klasbuffer += "\r\n:#'''''" + (prop.HasPropertyFlag(PropertyFlagsLO.OptionalParm)
                                    ? "[[optional]] "
                                    : "") + "[[" + typetext + (typetext != friendlytypetext
                                    ? "|" + friendlytypetext
                                    : "") + "]]''''' '''" + prop.Name + "''' - '''???.'''";
                            }
                        }

                        klasbuffer += "\r\n";
                    }
                }

                if (!string.IsNullOrEmpty(klasbuffer))
                {
                    buffer += "==" + package.PackageName + " Commands==\r\n" + klasbuffer + "\r\n";
                }

                package.Stream.Close();
            }

            buffer +=
                "\r\n==External links==\r\n* [[udn2:ConsoleCommands|Native Console Commands]]\r\n\r\n[[Category:Console Commands]]";
            string savePath = Path.Combine(Application.StartupPath,
                engineprefix + " Console Commands (" + gameprefix + ").txt");
            File.WriteAllText(savePath, buffer);
            Process.Start(savePath);
        }
    }
}